package com.glasses.manage.core.dao;

import com.glasses.manage.core.entity.BaseEntity;
import com.glasses.manage.core.entity.PageBean;
import com.glasses.manage.core.entity.PageParam;
import com.glasses.manage.core.exception.DataAccessException;
import com.glasses.manage.core.exception.DataAccessExceptionType;
import com.glasses.manage.core.mybatis.interceptor.ExecutorInterceptor;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @描述: 数据访问层基础支撑类
 * @作者 Mr.yy
 * @创建时间 2017/6/14
 * @版本: 1.0
 */
public class BaseDaoImpl<T extends BaseEntity> extends AbstractBaseDao implements BaseDao<T> {

    protected static final Logger log = LoggerFactory.getLogger(BaseDaoImpl.class);

    public static final String SQL_INSERT = "insert";
    public static final String SQL_BATCH_INSERT = "batchInsert";
    public static final String SQL_UPDATE = "update";
    public static final String SQL_GET_BY_ID = "getById";
    public static final String SQL_DELETE = "delete";
    public static final String SQL_DELETE_BY_ID = "deleteById";
    public static final String SQL_DELETE_BY_IDS = "deleteByIds";
    public static final String SQL_LIST_PAGE = "listPage";
    public static final String SQL_LIST_BY = "listBy";
    public static final String SQL_COUNT_BY_PAGE_PARAM = "countByPageParam"; // 根据当前分页参数进行统计

    /**
     * 注入SqlSessionTemplate实例(要求Spring中进行SqlSessionTemplate的配置).<br/>
     * 可以调用sessionTemplate完成数据库操作.
     */
    @Autowired
    private SqlSessionTemplate sessionTemplate;


    public SqlSessionTemplate getSessionTemplate() {
        return sessionTemplate;
    }

    public void setSessionTemplate(SqlSessionTemplate sessionTemplate) {
        this.sessionTemplate = sessionTemplate;
    }

    public SqlSession getSqlSession() {
        return super.getSqlSession();
    }

    public long insert(T t) {

        if (t == null)
            throw new RuntimeException("T is null");

        int result = sessionTemplate.insert(getStatement(SQL_INSERT), t);

        if (result <= 0)
            throw new DataAccessException(DataAccessExceptionType.DB_INSERT_RESULT_0);
        if (t != null && t.getId() != null && result > 0)
            return t.getId();

        return result;
    }

    public long insert(List<T> list) {

        if (list == null || list.size() <= 0)
            return 0;

        int result = sessionTemplate.insert(getStatement(SQL_BATCH_INSERT), list);

        if (result <= 0)
            throw new DataAccessException(DataAccessExceptionType.DB_INSERT_RESULT_0);

        return result;
    }

    public int update(T t) {
        if (t == null)
            throw new RuntimeException("T is null");

        int result = sessionTemplate.update(getStatement(SQL_UPDATE), t);

        if (result <= 0)
            throw new DataAccessException(DataAccessExceptionType.DB_UPDATE_RESULT_0);

        return result;
    }


    public int update(List<T> list) {

        if (list == null || list.size() <= 0)
            return 0;

        int result = 0;

        for (int i = 0; i < list.size(); i++) {
            this.update(list.get(i));
            result += 1;
        }

        if (result <= 0)
            throw new DataAccessException(DataAccessExceptionType.DB_UPDATE_RESULT_0);

        return result;
    }

    public int update(Map<String, Object> paramMap, String sqlId) {

        int result = sessionTemplate.update(getStatement(sqlId), paramMap);
        if (result <= 0)
            throw new DataAccessException(DataAccessExceptionType.DB_UPDATE_RESULT_0);
        return result;
    }

    public T getById(long id) {
        T t = sessionTemplate.selectOne(getStatement(SQL_GET_BY_ID), id);
        return t;
    }


    public int deleteById(long id) {
        return sessionTemplate.delete(getStatement(SQL_DELETE_BY_ID), id);
    }

    public int deleteByIds(List<Long> ids) {
        return sessionTemplate.delete(getStatement(SQL_DELETE_BY_IDS), ids);
    }

    public int delete(Map<String, Object> paramMap, String sqlId) {
        return sessionTemplate.delete(getStatement(sqlId), paramMap);
    }

    public int delete(Map<String, Object> paramMap) {
        return sessionTemplate.delete(getStatement(SQL_DELETE), paramMap);
    }


    public PageBean listPage(PageParam pageParam, Map<String, Object> paramMap) {
        return this.listPage(pageParam, paramMap, SQL_LIST_PAGE);
    }

    public PageBean listPage(PageParam pageParam, Map<String, Object> paramMap, String sqlId) {
        return this.listPage(pageParam, paramMap, sqlId, null);
    }


    @Override
    public PageBean listPage(PageParam pageParam, Map<String, Object> paramMap, String sqlId, String countSqlId) {

        logger.info("[请求分页参数]:" + pageParam + ",[请求查询参数]:" + paramMap);

        if (pageParam == null)
            throw new DataAccessException(DataAccessExceptionType.DB_NULL_PAGE_PARAMS);


        if (paramMap == null) {
            paramMap = new HashMap<String, Object>();
        }

        if (pageParam != null) {
            if (pageParam.getOrder() != null && !"".equals(pageParam.getOrder().trim())) {
                paramMap.put("order", pageParam.getOrder());
            }
            if (pageParam.getSort() != null && !"".equals(pageParam.getSort().trim())) {
                paramMap.put("sort", pageParam.getSort());
            }
        }

        // 获取分页数据集 , 注切勿换成 sessionTemplate 对象
        List<Object> list = getSqlSession().selectList(getStatement(sqlId), paramMap, new RowBounds((pageParam.getPageNum() - 1) * pageParam.getNumPerPage(), pageParam.getNumPerPage()));
        Long count = 0L;
        // 统计总记录数
        if (countSqlId == null) {
            Object countObject = getSqlSession().selectOne(getStatement(sqlId), new ExecutorInterceptor.CountParameter(paramMap));
            count = Long.valueOf(countObject.toString());
        } else {
            Object countObject = getSqlSession().selectOne(getStatement(countSqlId), paramMap);
            count = Long.valueOf(countObject.toString());
        }

        // 是否统计当前分页条件下的数据：1:是，其他为否
        Object isCount = paramMap.get("isCount");
        if (isCount != null && "1".equals(isCount.toString())) {
            Map<String, Object> countResultMap = sessionTemplate.selectOne(getStatement(SQL_COUNT_BY_PAGE_PARAM), paramMap);
            return new PageBean(pageParam.getPageNum(), pageParam.getNumPerPage(), count.intValue(), list, countResultMap);
        }

        return new PageBean(pageParam.getPageNum(), pageParam.getNumPerPage(), count.intValue(), list);
    }


    public List<T> listBy(Map<String, Object> paramMap) {
        List<T> list = this.listBy(paramMap, SQL_LIST_BY);
        return list;
    }


    public <E> List<E> listBy(Map<String, Object> paramMap, String sqlId) {
        if (paramMap == null)
            paramMap = new HashMap<String, Object>();
        List<E> list = sessionTemplate.selectList(getStatement(sqlId), paramMap);
        return list;
    }

    @SuppressWarnings("unchecked")
    public T getBy(Map<String, Object> paramMap) {
        T t = (T) this.getBy(paramMap, SQL_LIST_BY);
        return t;
    }


    public Object getBy(Map<String, Object> paramMap, String sqlId) {
        if (paramMap == null || paramMap.isEmpty())
            return null;

        Object obj = this.getSqlSession().selectOne(getStatement(sqlId), paramMap);
        return obj;
    }

    public String getStatement(String sqlId) {

        String name = this.getClass().getName();

        StringBuffer sb = new StringBuffer().append(name).append(".").append(sqlId);

        return sb.toString();
    }


}
